package p.ithorns.sample.influxdb.mapper;

import lombok.extern.slf4j.Slf4j;
import p.ithorns.framework.common.utils.StringUtil;
import p.ithorns.framework.common.utils.TypeConverter;
import p.ithorns.sample.influxdb.core.BeanUtil;
import p.ithorns.sample.influxdb.core.QueryRecord;

import java.lang.reflect.Field;
import java.time.DateTimeException;
import java.time.Instant;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

/**
 * QLResultBeanMapper
 *
 * @author HtL
 * @date 2025/1/16 11:03
 * @since 1.0.0
 */
@Slf4j
public class QLResultBeanMapper {

    public QLResultBeanMapper() {
        // 注册Instant类型转换器
        registerInstantConverter();
    }

    public <T> T toBean(QueryRecord record, Class<T> clazz ) {
        Map<String, Field> classFields = BeanUtil.getClassFields(clazz);
        final T obj = BeanUtil.instance(clazz);
        LinkedHashMap<String, Object> values = record.getValues();

        Set<Map.Entry<String, Field>> entries = classFields.entrySet();
        for (Map.Entry<String, Field> entry : entries) {
            String key = entry.getKey();
            Field field = entry.getValue();
            if (null != field) {
                Object value = values.get(key);
                setValue(obj, field, value);
            }
        }
        return   obj;
    }

    private <T> void setValue(T obj, Field field, Object value) {
        try {
            Class<?> valueType = field.getType();
            Object castValue = TypeConverter.convert(value, valueType);
            field.set(obj, castValue);
        } catch (IllegalArgumentException e) {
            log.error("参数类型不匹配:{}", value, e);
        } catch (IllegalAccessException e) {
            log.error("参数异常:{}", value, e);
        }
    }

    private void registerInstantConverter() {
        TypeConverter.registerConverter(Instant.class, value -> {
            if (value instanceof Number) {
                return Instant.ofEpochMilli(((Number) value).longValue());
            } else if (value instanceof String str) {
                if (TypeConverter.isNullStr(str)) {
                    return null;
                }

                if (StringUtil.isNumeric(str)) {
                    try {
                        long l = Long.parseLong(str);
                        return Instant.ofEpochMilli(l / 1000000);
                    } catch (NumberFormatException e) {
                        // log.error(e.getMessage());
                        throw new IllegalArgumentException("Failed to parse " + value + " to Instant", e);
                    }
                } else {
                    try {
                        return Instant.parse(str);
                    } catch (DateTimeException e) {
                        throw new IllegalArgumentException("Failed to parse " + value + " to Instant", e);
                    }
                }
            } else {
                throw new IllegalArgumentException("Unsupported conversion from " + value.getClass() + " to Integer");
            }
        });
    }

}